#pragma once

//
// Ensures that this sensor is created and registered with the
// sensor registry.  Parameter "T" must be a concrete sub-class
// of "CSensor" and must define a default constructor.
//
#define IMPLEMENT_SENSOR(T)		CSensorRegistrar<T> ___g___T##_Registrar

//
// This class represents a single sensor on the device. It
// has the following responsiblities
//	- manage all the data and properties on the sensor
//	- manage I/O with the actual device
//	- raise events at appropriate times by calling upon
//	  the events manager
//	- manage the state of the sensor
//	- register itself with the sensor registry during load
//
class CSensor : public CAutoCriticalSectionLockable<CSensor>
{
protected:
	bool					m_bInitialized;	// tracks whether sensor initialization is complete
	SensorState				m_State;		// current state of this sensor
	CPortableDeviceProps	m_Properties;	// sensor properties
	CPortableDeviceProps	m_Data;			// sensor data fields
	CComPtr<IWDFDevice>		m_spDevice;		// pointer to the WDF device object
	CSensorDDI				*m_pSensorDDI;	// pointer to the "CSensorDDI" object

public:
	CSensor(void);
	virtual ~CSensor(void);

	//
	// Initialize this sensor.
	//
	virtual HRESULT Init(IWDFDevice *pDevice, CSensorDDI *pSensorDDI);

	//
	// Sets the current state.  Returns the old state.
	//
	SensorState SetState(SensorState state);
	virtual void OnStateChange(SensorState oldState, SensorState newState);

	//
	// Getters for common sensor properties.
	//
	virtual wstring GetId() const = 0;						// retrieve sensor id
	virtual wstring GetName() const = 0;					// retrieve name of the sensor
	virtual GUID GetPUID() const;							// retrieve persistent unique id
	virtual wstring GetParentId() const;					// retrieve parent object id
	virtual GUID GetFormat() const;							// retrieve identifier for the format of
															// the content generated by this sensor
	virtual GUID GetContentType() const;					// retrieve identifier for the type of content
															// generated by this sensor
	virtual bool GetCanDelete() const;						// retrieve boolean to determine whether this
															// object can be deleted
	virtual GUID GetFunctionalObjectCategory() const = 0;	// retrieve functional object category

	//
	// start I/O cycle
	//
	virtual HRESULT StartIO(IWDFDevice*);

	//
	// stop I/O cycle
	//
	virtual HRESULT StopIO(IWDFDevice*);

	//
	// get the supported properties
	//
	virtual HRESULT GetSupportedProperties(IPortableDeviceKeyCollection **ppKeys) const;

	//
	// get the supported data fields
	//
	virtual HRESULT GetSupportedDataFields(IPortableDeviceKeyCollection **ppKeys) const;

	//
	// get the data fields
	//
	virtual HRESULT GetDataFields(IPortableDeviceKeyCollection *pDataFields,
								  IPortableDeviceValues **ppDataValues) const;

	//
	// get the properties
	//
	virtual HRESULT GetProperties(IPortableDeviceKeyCollection *pPropFields,
								  IPortableDeviceValues **ppPropValues) const;

protected:
	HRESULT GetDeviceValues(const CPortableDeviceProps& deviceProps,
						    IPortableDeviceKeyCollection *pPropFields,
						    IPortableDeviceValues **ppPropValues) const;
	HRESULT GetSupportedKeys(const CPortableDeviceProps& props, IPortableDeviceKeyCollection **ppKeys) const;
	HRESULT CopyKeys(IPortableDeviceKeyCollection *pFrom, IPortableDeviceKeyCollection *pTo) const;
};
